﻿Imports System.ComponentModel

Public Class FrmTablero

#Region "variables"
    Dim tablero(8, 8) As String
    Dim fila() As String = {"", "8", "7", "6", "5", "4", "3", "2", "1"}
    Dim columna() As String = {"", "a", "b", "c", "d", "e", "f", "g", "h"}
    Public tableroAjedrez As New Tablero
    Dim figura As piezas
    Dim repetido(63) As String
    Public posiscionCaballoNegro As String
    Dim cursorCB As Cursor
    Dim caminosol As Queue
    Dim recorrido As String
    Dim cantMovs As Integer
    Dim miliseg, seg, min As Integer
    Dim usoMem As Integer
    Dim timeEj As TimeSpan
    Dim tim As Integer
    Public pausar, parar As Boolean
    Public terminar As Boolean = False
#End Region

#Region "Formulario"

    Private Sub FrmTablero_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        CrearTreeView()

    End Sub

#End Region

#Region "Tablero"
    Private Sub CrearTreeView()
        Try
            Dim i As Integer
            Dim Alto As Integer = 75
            Dim ancho As Integer = 75
            Dim x, y As Integer

            x = 0
            y = 0
            For i = 1 To 8
                For j As Integer = 1 To 8
                    Dim TrwTableroAjedrez As New Button

                    'Coloco todas las aulas en el turno de examen 
                    tablero(i, j) = columna(i) + fila(j) + "  (" + CStr(i) + "," + CStr(j) + ")"

                    TrwTableroAjedrez.Text = CStr(i) + CStr(j) 'tablero(i, j)

                    TrwTableroAjedrez.Tag = CStr(i) + CStr(j)

                    TrwTableroAjedrez.Size = New Size(ancho, Alto)

                    If par(i, j) Then
                        TrwTableroAjedrez.BackColor = Color.White
                    Else
                        TrwTableroAjedrez.BackColor = Color.Gray

                    End If


                    TrwTableroAjedrez.Location = New Point(Me.Button1.Width + x, Me.LBIterar.Height + y)
                    Me.Panel1.Controls.Add(TrwTableroAjedrez)
                    TrwTableroAjedrez.Show()

                    x += ancho
                Next
                x = 0
                y += Alto
            Next

            For Each c As Button In Me.Panel1.Controls
                AddHandler c.Click, AddressOf Me.insertar
            Next
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
#End Region

#Region "Funciones"

    Private Function par(ByVal fila As Integer, ByVal col As Integer) As Boolean
        Dim res As Integer = fila + col
        If res Mod 2 = 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    'Busca una figura dentro del tablero del formulario, funcionaría para el caballo negro
    Private Function obtenerPosicion(ByVal figura As piezas) As String
        Dim boton As Object
        Dim i As IEnumerator
        For Each boton In Me.Panel1.Controls
            If boton.GetType.Name = "Button" Then
                If Not boton.tag Is Nothing Then
                    i = boton.tag.getenumerator
                    i.MoveNext()
                    If Not CType(boton, Button).Image Is Nothing Then
                        If CType(boton, Button).Image.Tag = figura Then
                            Return (CStr(CType(boton, Button).Tag)) 'Esto tiene el nombre de la celda
                        End If
                    End If

                End If
            End If

        Next
    End Function
    'Verifica que no genere dos caballos blancos en la misma posición
    Private Function verificarRepetido(ByVal nro As String) As Boolean

        verificarRepetido = False

        For i As Integer = 0 To 63
            If repetido(i) = nro Then
                verificarRepetido = True
                Exit For
            End If

        Next

        Return verificarRepetido

    End Function
    'Calcula el consumo de memoria que está utilizando el proceso en ejecución (Kb)
    Public Function consumoMem() As Double
        Dim p As System.Diagnostics.Process = System.Diagnostics.Process.GetCurrentProcess
        Dim val As Double
        val = p.WorkingSet64 / 1024
        Return val
    End Function

#End Region

#Region "Procedimientos"
    Private Sub insertar(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            Dim contenido, posicion As String
            contenido = tableroAjedrez.obtenerFigura(CType(sender, Button).Tag)
            posicion = CType(sender, Button).Tag
            If Me.Cursor.Tag = "blanco" And contenido <> piezas.blanco And contenido <> piezas.negro Then

                CType(sender, Button).Image = imgCaballo.Images(figura)
                tableroAjedrez.cargarFigura(posicion, figura)
            ElseIf Me.Cursor.Tag = "blanco" And contenido = piezas.blanco Then

                CType(sender, Button).Image = Nothing
                tableroAjedrez.cargarFigura(posicion, piezas.vacio) 'coloco un vacio como figura
                tableroAjedrez.DesContador()
            End If


            If Me.Cursor.Tag = "negro" And contenido <> piezas.negro And contenido <> piezas.blanco Then
                If posiscionCaballoNegro <> "" Then
                    limpiarPosicion(posiscionCaballoNegro)
                End If
                posiscionCaballoNegro = posicion
                tableroAjedrez.cargarFigura(posiscionCaballoNegro, piezas.vacio)
                CType(sender, Button).Image = imgCaballo.Images(figura)

                tableroAjedrez.cargarFigura(posicion, figura)
                tableroAjedrez.ContadorCaballoNegro1 = True
            End If
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

    End Sub

    'inserta una cantidad dada de caballos blancos en el formulario
    Private Sub InsertaBlanco(ByVal cantidad As Integer)
        figura = piezas.blanco
        Dim pos As String
        Dim list As ArrayList
        list = New ArrayList(64) '{11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 36, 37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 71, 72, 73, 74, 75, 76, 77, 78, 81, 82, 83, 87, 84, 85, 86, 87, 88}
        Dim nro As Integer
        For i As Integer = 1 To 8
            For j As Integer = 1 To 8
                nro = CStr(i) + CStr(j)
                list.Add(nro)
            Next
        Next
        While cantidad > 0
            Do
                pos = CStr(Funciones.randomIntento(list))
            Loop While tableroAjedrez.obtenerFigura(pos) <> "2"
            tableroAjedrez.cargarFigura(pos, figura)
            Me.buscarPosicion(pos)
            cantidad = cantidad - 1

        End While
    End Sub
    Private Sub InsertaBlancoLogico(ByVal cantidad As Integer)
        figura = piezas.blanco
        Dim pos As String
        Dim list As ArrayList
        list = New ArrayList(64) '{11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 36, 37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 51, 52, 53, 54, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 71, 72, 73, 74, 75, 76, 77, 78, 81, 82, 83, 87, 84, 85, 86, 87, 88}
        Dim nro As Integer
        For i As Integer = 1 To 8
            For j As Integer = 1 To 8
                nro = CStr(i) + CStr(j)
                list.Add(nro)
            Next
        Next
        While cantidad > 0
            Do
                pos = CStr(Funciones.randomIntento(list))
            Loop While tableroAjedrez.obtenerFigura(pos) <> "2"
            tableroAjedrez.cargarFigura(pos, figura)
            cantidad = cantidad - 1

        End While
    End Sub

    'es llamada desde insertarblanco y carga en un vector todas las posiciones generadas donde no se puede cargar un caballo
    Private Sub insertarRepetido(ByVal nro As Integer)
        For i As Integer = 0 To 63
            If repetido(i) = "" Then
                repetido(i) = nro
                Exit For
            End If

        Next
    End Sub
    'busca una posicion dentro del arreglo de controles y le inserta una figura ya sea caballo blanco o negro
    Private Sub buscarPosicion(ByVal posicion As String)
        Dim boton As Object
        Dim i As IEnumerator
        For Each boton In Me.Panel1.Controls
            If boton.GetType.Name = "Button" Then
                If Not boton.tag Is Nothing Then
                    i = boton.tag.getenumerator
                    i.MoveNext()
                    If CStr(CType(boton, Button).Tag) = posicion Then
                        CType(boton, Button).Image = imgCaballo.Images(figura)
                        CType(boton, Button).Image.Tag = figura

                    End If
                End If
            End If

        Next

    End Sub
    'borra todas las figuras de caballo que haya en el formulario
    Private Overloads Sub limpiarPosicion()
        Dim boton As Object
        Dim i As IEnumerator
        For Each boton In Me.Panel1.Controls
            If boton.GetType.Name = "Button" Then
                If Not boton.tag Is Nothing Then
                    i = boton.tag.getenumerator
                    i.MoveNext()

                    CType(boton, Button).Image = Nothing


                End If
            End If

        Next
    End Sub
    'limpia una celda dada por su nombre
    Private Overloads Sub limpiarPosicion(ByVal pos As String)
        If posiscionCaballoNegro <> "" Then
            Dim boton As Object
            Dim i As IEnumerator
            For Each boton In Me.Panel1.Controls

                If boton.GetType.Name = "Button" Then
                    If Not boton.tag Is Nothing Then
                        i = boton.tag.getenumerator
                        i.MoveNext()
                        If CStr(CType(boton, Button).Tag) = pos Then
                            CType(boton, Button).Image = Nothing
                        End If
                    End If
                End If
            Next
            tableroAjedrez.limpiarTablero(pos)
        End If
    End Sub
    'mueve a una posicion aleatorio el caballo, se usa al apretar el boton o cargar el formulario
    Private Overloads Sub moverCaballoNegro()
        figura = piezas.negro
        posiscionCaballoNegro = Funciones.randomPosicionXY
        Me.buscarPosicion(tableroAjedrez.obtenerPosicion(posiscionCaballoNegro))

    End Sub
    'mueve caballo negro a una posicion dada de acuerdo a los indices
    Private Overloads Sub moverCaballoNegro(ByVal posx As String, ByVal posy As String)
        If posiscionCaballoNegro <> "" Then
            tableroAjedrez.cargarFigura(posiscionCaballoNegro, piezas.vacio)
            Me.limpiarPosicion(posiscionCaballoNegro)
            'Me.limpiarPosicion(tableroAjedrez.obtenerPosicion(posiscionCaballoNegro))
        End If
        Me.posiscionCaballoNegro = CStr(posx) + CStr(posy)
        Me.buscarPosicion(posiscionCaballoNegro)
        tableroAjedrez.cargarFigura(posiscionCaballoNegro, figura)

    End Sub
    Sub pruebas(ByVal cant As Integer)
        Dim posCN As Integer = CInt(Funciones.randomPosicionXY)
        Dim caminoprof, caminoamp, caminoae As Queue
        Dim tiempo1prof, tiempo1amp, tiempo1ae, tiempo2prof, tiempo2amp, tiempo2ae As DateTime
        Dim totalTimeprof, totalTimeamp, totalTimeae As TimeSpan
        Dim var2prof, var2amp, var2ae, var3prof, var3amp, var3ae As Double
        Dim totalmemprof, totalmemamp, totalmemae As Double
        tableroAjedrez.limpiarTablero()
        tableroAjedrez.cargarFigura(CStr(posCN), piezas.negro)
        InsertaBlancoLogico(cant)
        If FrmPruebas.CBprof.Checked Then
            caminoprof = New Queue
            tiempo1prof = DateTime.Now
            var2prof = consumoMem()
            caminoprof = tableroAjedrez.primeroprof(Me.tableroAjedrez, posCN)
            var3prof = consumoMem()
            tiempo2prof = DateTime.Now
            totalTimeprof = New TimeSpan(tiempo2prof.Ticks - tiempo1prof.Ticks)
            totalmemprof = (var3prof - var2prof)
            FrmPruebas.totalmemprof = totalmemprof
            FrmPruebas.totalTimeprof = totalTimeprof
            FrmPruebas.tamcamprof = (caminoprof.Count - 1)
        End If
        If FrmPruebas.CBamp.Checked Then
            caminoamp = New Queue
            tiempo1amp = DateTime.Now
            var2amp = consumoMem()
            caminoamp = tableroAjedrez.primeroamplitud(Me.tableroAjedrez, posCN)
            var3amp = consumoMem()
            tiempo2amp = DateTime.Now
            totalTimeamp = New TimeSpan(tiempo2amp.Ticks - tiempo1amp.Ticks)
            totalmemamp = (var3amp - var2amp)
            FrmPruebas.totalmemamp = totalmemamp
            FrmPruebas.totalTimeamp = totalTimeamp
            FrmPruebas.tamcamamp = (caminoamp.Count - 1)
        End If
        If FrmPruebas.CBaestrella.Checked Then
            caminoae = New Queue
            tiempo1ae = DateTime.Now
            var2ae = consumoMem()
            caminoae = tableroAjedrez.Aestrella(Me.tableroAjedrez, posCN)
            var3ae = consumoMem()
            tiempo2ae = DateTime.Now
            totalTimeae = New TimeSpan(tiempo2ae.Ticks - tiempo1ae.Ticks)
            totalmemae = (var3ae - var2ae)
            FrmPruebas.totalmemae = totalmemae
            FrmPruebas.totalTimeae = totalTimeae
            FrmPruebas.tamcamae = (caminoae.Count - 1)
        End If
    End Sub
    Public Sub nuevoTablero()
        tableroAjedrez.limpiarTablero()
        limpiarPosicion()
        posiscionCaballoNegro = ""
    End Sub
#End Region

#Region "Botones"
    Private Sub btnCaballoNegro_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCaballoNegro.Click

        Dim ms As New System.IO.MemoryStream(My.Resources.caballo_negro)
        If Me.Cursor.Tag = "" Or Me.Cursor.Tag = "blanco" Then
            Me.Cursor = New Cursor(ms)
            Me.Cursor.Tag = "negro"
        Else
            Me.Cursor = Cursors.Arrow
        End If

        figura = piezas.negro
        
    End Sub

    Private Sub btnCaballoBlanco_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCaballoBlanco.Click
        Dim ms As New System.IO.MemoryStream(My.Resources.caballo_blanco)
        If Me.Cursor.Tag = "" Or Me.Cursor.Tag = "negro" Then
            Me.Cursor = New Cursor(ms)
            Me.Cursor.Tag = "blanco"
        Else
            Me.Cursor = Cursors.Arrow
        End If

        figura = piezas.blanco

    End Sub
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim res As String
        res = ""
        For i As Integer = 1 To 8

            For j As Integer = 1 To 8
                res = res + "       " + CStr(i) + CStr(j) + " = " + tableroAjedrez.obtenerFigura(i, j)
            Next
            res = res + vbNewLine

        Next
        res = res + vbNewLine + " cantida caballos blancos " + CStr(tableroAjedrez.CantidadCaballoBlanco) + vbNewLine + " Posición caballo negro " + CStr(posiscionCaballoNegro)

        MsgBox(res)

    End Sub
    Private Sub pasoPaso_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pasoPaso.Click
        Me.Cursor = Cursors.Default
        If tableroAjedrez.ContadorCaballoNegro1 And tableroAjedrez.CantidadCaballoBlanco > 0 Then
            terminar = False
            pasoPaso.Enabled = False
            If primeroprof.Checked Or primeroamplitud.Checked Or heuristica.Checked Then
                Dim var As New Microsoft.VisualBasic.Devices.ComputerInfo
                Dim var2, var3, totalmem As Double
                Dim tiempo1, tiempo2 As DateTime
                Dim totalTime As TimeSpan
                BTStop.Enabled = True
                var2 = consumoMem()
                miliseg = seg = min = 0
                tiempoEjecucion.Enabled = True
                tiempoEjecucion.Interval = 1000
                LBNumer.Text = "0"
                tim = 0
                caminosol = New Queue
                Timer4.Interval = 1000
                Timer4.Enabled = True
                LBNumer.Visible = True
                LBIterar.Visible = True
                If primeroprof.Checked Then
                    tiempo1 = DateTime.Now
                    caminosol = tableroAjedrez.primeroprof(Me.tableroAjedrez, posiscionCaballoNegro)
                    var3 = consumoMem()
                    tiempo2 = DateTime.Now
                    cantMovs = caminosol.Count
                ElseIf primeroamplitud.Checked Then
                    tiempo1 = DateTime.Now
                    caminosol = tableroAjedrez.primeroamplitud(Me.tableroAjedrez, posiscionCaballoNegro)
                    var3 = consumoMem()
                    tiempo2 = DateTime.Now
                    cantMovs = caminosol.Count
                ElseIf heuristica.Checked Then
                    tiempo1 = DateTime.Now
                    caminosol = tableroAjedrez.Aestrella(Me.tableroAjedrez, posiscionCaballoNegro)
                    var3 = consumoMem()
                    tiempo2 = DateTime.Now
                    cantMovs = caminosol.Count
                End If

                totalmem = (var3 - var2)
                usoMem = totalmem
                If Not terminar Then
                    tempMov.Enabled = True
                    tempMov.Interval = 1000
                    pausa.Enabled = True
                    solucionDirecta.Enabled = True
                End If
                totalTime = New TimeSpan(tiempo2.Ticks - tiempo1.Ticks)
                timeEj = totalTime
                Timer4.Enabled = False
                LBNumer.Visible = False
                LBIterar.Visible = False
                BTStop.Enabled = False
                LBNumer.Text = "0"
                If terminar Then
                    MsgBox("El proceso ha sido detenido")
                End If


            End If
        End If
    End Sub
    Private Sub pausa_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles pausa.Click
        If pausar Then
            pausar = False
            pausa.BackgroundImage = IMGBotones.Images(0)
            pausa.BackgroundImageLayout = ImageLayout.Stretch
        Else
            pausar = True
            pausa.BackgroundImage = IMGBotones.Images(1)
            pausa.BackgroundImageLayout = ImageLayout.Stretch
        End If
        If caminosol.Count > 0 Then
            If tempMov.Enabled Then
                tempMov.Enabled = False
            Else
                tempMov.Enabled = True
            End If
        End If
    End Sub
    Private Sub solucionDirecta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles solucionDirecta.Click
        If tempMov.Interval > 200 Then
            tempMov.Interval = tempMov.Interval - 200
        Else
            While caminosol.Count > 1
                caminosol.Dequeue()
            End While
        End If

    End Sub
    Private Sub BTStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BTStop.Click
        parar = True
    End Sub
#End Region

#Region "Menues"
    Private Sub Nuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Nuevo.Click
        nuevoTablero()
    End Sub

    Private Sub TSMCabNeg_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TSMCabNeg.Click
        Dim ofrm As New frmInsertarCaballo
        figura = piezas.negro
        ofrm.ShowDialog()
        If ofrm.posicionX <> 0 And ofrm.posicionY <> 0 Then
            Me.moverCaballoNegro(ofrm.posicionX, ofrm.posicionY)
        End If
    End Sub

    Private Sub TSMCabBlan_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TSMCabBlan.Click
        Dim ofrm As New FrmInsertarBlanco
        ofrm.ShowDialog()
        figura = piezas.blanco
        If Not ofrm.habilitarVarios Then

            Me.buscarPosicion(tableroAjedrez.obtenerPosicion(ofrm.posicionX, ofrm.posicionY))
        Else
            While (tableroAjedrez.CantidadCaballoBlanco + ofrm.cantidad) > 63
                MsgBox("introduzca un numero menor que 63")
                ofrm.ShowDialog()
            End While

            Me.InsertaBlanco(ofrm.cantidad)
        End If
    End Sub
    Private Sub MIAleatorias_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MIAleatorias.Click
        FrmPruebas.ShowDialog()
    End Sub

    Private Sub MIContraTab_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MIContraTab.Click
        If tableroAjedrez.ContadorCaballoNegro1 And tableroAjedrez.CantidadCaballoBlanco > 0 Then
            FrmPruebasIndividuales.ShowDialog()
        Else
            MsgBox("Debe agregar una configuración válida de tablero para poder realizar estas pruebas.")
        End If
    End Sub
#End Region

#Region "Eventos"
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tempMov.Tick
        Dim estado As New Tablero
        If caminosol.Count > 0 Then
            estado = caminosol.Dequeue
            For i As Integer = 1 To 8

                For j As Integer = 1 To 8
                    If estado.obtenerFigura(i, j) = CStr(piezas.blanco) Then
                        figura = piezas.blanco
                        Me.buscarPosicion(CStr(i) + CStr(j))
                    ElseIf estado.obtenerFigura(i, j) = CStr(piezas.negro) Then
                        figura = piezas.negro
                        Me.buscarPosicion(CStr(i) + CStr(j))
                        recorrido = "pos " + CStr(i) + CStr(j) + vbNewLine
                    ElseIf estado.obtenerFigura(i, j) = CStr(piezas.vacio) Or estado.obtenerFigura(i, j) = CStr(piezas.paso) Then
                        Me.limpiarPosicion(CStr(i) + CStr(j))
                    End If
                Next


            Next
            If caminosol.Count = 0 Then
                tempMov.Enabled = False
                If primeroprof.Checked Then
                    FrmVerResultados.LBAlg.Text = CStr("Primero en Profundidad")
                ElseIf primeroamplitud.Checked Then
                    FrmVerResultados.LBAlg.Text = CStr("Primero en Amplitud")
                ElseIf heuristica.Checked Then
                    FrmVerResultados.LBAlg.Text = CStr("A*")
                End If
                FrmVerResultados.LBCantCBs.Text = CStr(tableroAjedrez.CantidadCaballoBlanco)
                FrmVerResultados.LBLongCam.Text = CStr(cantMovs - 1)
                FrmVerResultados.LBUsoMem.Text = CStr(usoMem) + " KB"
                FrmVerResultados.LBTimeEj.Text = CStr(timeEj.Hours) + " : " + CStr(timeEj.Minutes) + " : " + CStr(timeEj.Seconds) + " : " + CStr(timeEj.Milliseconds)
                FrmVerResultados.LBPosCN.Text = CStr(posiscionCaballoNegro)
                FrmVerResultados.ShowDialog()
                pausa.Enabled = False
                BTStop.Enabled = False
                solucionDirecta.Enabled = False
                pasoPaso.Enabled = True
                caminosol.Clear()
            End If
        Else
            tempMov.Enabled = False
            MsgBox("No se encontró una solución")
        End If
    End Sub
    Private Sub Timer4_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer4.Tick, tempMov.Tick
        tim = tim + 1
        LBNumer.Text = CStr(tim)
        Me.Refresh()
    End Sub
#End Region

End Class
